package com.fys.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


/**
 * Hystrix服务降级的应用：
 *  1.目标服务不能正常提供服务时降级
 *  2.可以对异常进行降级
 *  3.降级超时时间的设置：请求第三方，如开户，充值，代扣这种业务可能耗费时间较长，那么超时时间就设置长一点
 * Hystrix服务熔断：
    1.熔断就跟保险丝一样的，如果温度过高，就会切断保险丝。如果要恢复，我们需要手动重启开关
 *  2.熔断可以在全局配置文件中配置
* @Param:
* @Return:
* @Date:   2020/8/26 18:25
* @Author: fys
*/
@RestController
@RequestMapping("/hystrix")
//默认降级配置，表明该类下面所有的@HystrixCommand的降级方法均是defaultFallback
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    /**
     * 服务熔断：可在全局配置文件中配置
     * @Date:   2020/8/27 9:57
     * @Author: fys
     */
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  				//是否启用熔断
			@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),	    //请求数达到后才计算
			@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗
			@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),	//错误率
    })
    @GetMapping("/listForOrderircuit")
    public String listForOrderircuit(@RequestParam("number") Integer number){
        //如果走下面的接口调用，长时间出错，错误率达到设置的阈值，则会启动熔断。使得整个方法都会降级
        //过了你设置的时间后，此方法又会变得可用了。
        if(number % 2 == 0){
            return "success";
        }
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8081/productInfo/listForOrder",
                Arrays.asList("157875196366160022"),
                String.class);
    }



    /**
     * 服务降级：超时时间设置
     * @Date:   2020/8/27 9:57
     * @Author: fys
     */
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    @GetMapping("/listForOrderTimeOut")
    public String listForOrderTimeOut(){
        RestTemplate restTemplate = new RestTemplate();
        //商品服务的这个接口会设置休眠2秒钟，默认超时时间为1秒，所以会进行降级
        return restTemplate.postForObject("http://127.0.0.1:8081/productInfo/listForOrder",
                Arrays.asList("157875196366160022"),
                String.class);
    }

    /**
     * 服务超时或不可用降级
     * @Date:   2020/8/27 9:57
     * @Author: fys
     */
    @HystrixCommand(fallbackMethod = "fallBack")
    @GetMapping("/listForOrder")
    public String listForOrder(){
        RestTemplate restTemplate = new RestTemplate();
        //商品服务的这个接口会设置休眠2秒钟，默认超时时间为1秒，所以会进行降级
        return restTemplate.postForObject("http://127.0.0.1:8081/productInfo/listForOrder",
                Arrays.asList("157875196366160022"),
                String.class);
    }

    /**
    * 异常降级
    * @Date:   2020/8/27 9:57
    * @Author: fys
    */
    @HystrixCommand(fallbackMethod = "fallBack")
    @GetMapping("/listForOrderException")
    public String listForOrderException(){
        throw new RuntimeException("发送异常了.....");
    }

    /**
     * 使用默认降级
     * @Date:   2020/8/27 9:57
     * @Author: fys
     */
    @HystrixCommand
    @GetMapping("/listForOrderDefault")
    public String listForOrderDefault(){
        throw new RuntimeException("发送异常了.....");
    }

    //降级方法
    public String fallBack(){
       return "太拥挤了，请稍后再试";
    }

    //默认降级方法
    public String defaultFallback(){
        return "默认降级:太拥挤了，请稍后再试";
    }


}
